package game

import (
	"GameServer/common"
	"GameServer/common/logger"
	"GameServer/db"
	jconf "GameServer/jsonconfig"
	"GameServer/pb"
	pmgr "GameServer/playermgr"
	"GameServer/utils"
	"bytes"
	"crypto/md5"
	"fmt"
	"strconv"

	"encoding/binary"

	"github.com/gin-gonic/gin"
	"github.com/golang/protobuf/proto"

	"io"
	"log"
	"net"
	"net/http"
	"os"
	"time"
)

const (
	HeartbeatInterval = 600 * time.Second
	ConnectionTimeout = 2000 * time.Second
)

func ConnWriter(player *common.GamePlayer) {
	if player == nil {
		logger.Info("conn writer routine start failed with nil player")
		return
	}
	player.LastAt = time.Now().Unix()
	logger.Info("conn writer routine start uid:%v seq:%v", player.UID, player.ConnSeq)
	//ticker := time.NewTicker(HeartbeatInterval)
	for {
		select {
		/*case <-ticker.C:
		deadline := time.Now().Add(-ConnectionTimeout).Unix()
		if player.LastAt < deadline {
			//心跳超时处理
			if player.Conn != nil {
				//通知客户端断开
				var msg pb.GameNoticeConnClosed
				msg.PlayerId = int32(player.UID)
				common.SendNoti(player, 0, uint32(player.UID), pb.MSGID_MsgID_Game_ConnClosed_Nty, &msg)
				logger.Notic("NoticeConnClosed,uid:%v", player.UID)
				//执行关闭操作
				err := player.Conn.Close()
				if err == nil {
					logger.Info("ConnWriter player close conn uid: %v", player.UID)
				} else {
					logger.Error("ConnWriter close conn err:%v, uid:%v", err, player.UID)
				}
			}
			//更新用户的在线状态
			//db.UpdatePlayerOnlineState(uint32(player.UID), 0)
			return
		}*/
		//主动回复心跳
		/*var resp pb.ResponseHeartBeat
		resp.Uid = int32(player.UID)
		header := pb.MessageHeader{0, 0, 0, 0, uint32(player.UID), 0}
		SendMessage(player, player.Conn, header, pb.MSGID_MsgID_HeartBeat_Response, &resp)
		logger.Notic("HeartBeatHandler resp:uid:%v", resp.Uid)*/
		case data := <-player.OutChannel:
			//todo send data to conn
			player.ConnLocker.Lock()
			conn := player.Conn
			player.ConnLocker.Unlock()

			WriteMessage2Conn(player.UID, conn, data)
		case _ = <-player.OutDone:
			logger.Info("conn writer routine end 2 uid:%v seq:%v", player.UID, player.ConnSeq)
			return
		}
	}
	logger.Info("conn writer routine end uid:%v seq:%v", player.UID, player.ConnSeq)
}

func WriteMessage2Conn(uid int, conn net.Conn, data []byte) {
	if conn == nil {
		return
	}
	conn.SetWriteDeadline(time.Now().Add(1 * time.Second))
	_, err := conn.Write(data)
	if err != nil {
		logger.Notic("send socket messeage error:%v uid:%v ip:%v", err, uid, conn.RemoteAddr().String)
	} else {
		//logger.Info("send socket message success for uid:%v data:%s", uid, conn.RemoteAddr().String())
	}
}

func Cors() gin.HandlerFunc {
	return func(context *gin.Context) {
		method := context.Request.Method
		context.Writer.Header().Set("Access-Control-Allow-Origin", "*")
		context.Header("Access-Control-Allow-Origin", "*") // 设置允许访问所有域
		context.Header("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE,UPDATE")
		context.Header("Access-Control-Allow-Headers", "Authorization, Content-Length, X-CSRF-Token, Token,session,X_Requested_With,Accept, Origin, Host, Connection, Accept-Encoding, Accept-Language,DNT, X-CustomHeader, Keep-Alive, User-Agent, X-Requested-With, If-Modified-Since, Cache-Control, Content-Type, Pragma,token,openid,opentoken")
		context.Header("Access-Control-Expose-Headers", "Content-Length, Access-Control-Allow-Origin, Access-Control-Allow-Headers,Cache-Control,Content-Language,Content-Type,Expires,Last-Modified,Pragma,FooBar")

		if method == "OPTIONS" {
			context.JSON(http.StatusOK, gin.H{"code": 1, "msg": "Options Request!"})
			return
		}
		context.Next()
	}
}

func Run() {
	f, err := os.Create("../log/http_game.log")
	if err != nil {
		log.Fatalln(err)
	}
	gin.DefaultWriter = io.MultiWriter(f)
	log.Println(f)
	log.Println("../log/http_game.log")

	router := gin.Default()
	router.Use(Cors())
	router.GET("/ClearData", ClearData)
	router.GET("/ReloadCfg", ReloadCfg)
	router.GET("/TestRpc", TestRpc)

	router.Run(":9000")
}

func SendMessage(player *common.GamePlayer, conn net.Conn, header pb.MessageHeader, msgid pb.MSGID, msg interface{}) bool {
	if conn == nil {
		logger.Notic("send message failed with nil conn, playerid:%v msgid:%v", header.PlayerID, msgid)
		return false
	}
	tmp, err := proto.Marshal(msg.(proto.Message))
	if err != nil {
		logger.Notic("send message marshal msgid:%v response body error:%v", msgid, err)
		return false
	}

	if player != nil {
		if !common.IsPlayerInPlayerMap(player.UID) {
			logger.Notic("send message player not in map, msgid:%v response body error:%v", msgid, err)
			return false
		}
	}

	if pb.MSGID(msgid) != pb.MSGID_MsgID_SC_Game_HeartBeat_Rsp {
		logger.Info("send message response uid:%v msgid:%+v", header.PlayerID, pb.MSGID(msgid))
	}
	/*var data []byte
	if msgid == pb.MSGID_MsgID_Logon_Response {
		logger.Notic("send message response logon, uid:%v, msg:%+v", header.PlayerID, msg)
		//rsa加密
		data, err = gorsa.RSA.PriKeyENCTYPT(tmp)
		if err != nil {
			logger.Notic("send message rsa encrypted msgid:%v  response body error:%v", msgid, err)
			return false
		}
	} else {
		//aes加密
		aesData, err := goEncrypt.AesCbcEncrypt(tmp, conf.EncryptCfg.AesKey, conf.EncryptCfg.AesIv...)
		if err != nil {
			logger.Notic("send message aes encrypted msgid:%v  response body error:%v", msgid, err)
			return false
		}
		bsData := base64.StdEncoding.EncodeToString(aesData)
		data = []byte(bsData)
	}*/
	data_len := len(tmp) + int(common.Min_Message_Size)
	//total_len := len(data) + int(common.Min_Message_Size)
	bys := new(bytes.Buffer)
	//binary.Write(bys, binary.BigEndian, uint16(total_len))
	binary.Write(bys, binary.BigEndian, uint16(data_len))
	binary.Write(bys, binary.BigEndian, uint16(msgid))
	binary.Write(bys, binary.BigEndian, uint32(header.Seq))
	binary.Write(bys, binary.BigEndian, uint32(header.PlayerID))
	binary.Write(bys, binary.BigEndian, uint32(header.ErrorCode))

	buf := append(bys.Bytes(), tmp...)

	if player != nil {
		select {
		case player.OutChannel <- buf:
			break
		case <-time.After(time.Millisecond * 20):
			logger.Notic("send message to uid:%v roomid:%v timeout, channel full", header.PlayerID, header.ErrorCode)
			return false
		}
	} else {
		//WriteMessage2Conn(player.UID, conn, buf)
		conn.SetWriteDeadline(time.Now().Add(1 * time.Second))
		_, err := conn.Write(buf)
		if err != nil {
			logger.Notic("send message send socket messeage error:%v ip:%v", err, conn.RemoteAddr().String)
		}
	}

	return true
}

func GenerateToken() string {
	crutime := time.Now().Unix()

	h := md5.New()

	io.WriteString(h, strconv.FormatInt(crutime, 10))

	token := fmt.Sprintf("%x", h.Sum(nil))
	fmt.Println("token--->", token)

	return token
}

func ConnCloseHandler(conn net.Conn, header pb.MessageHeader, msg interface{}) {
	//捕获异常
	defer utils.PrintPanicStack()
	//处理逻辑
	req := msg.(*pb.GameNoticeConnectionClose)
	logger.Info("ConnCloseHandler-connection closed:%v header:%v", req, header)
	player, er := pmgr.GetPlayerFromMap(int(header.PlayerID))
	if er != nil || player == nil {
		return
	}
	logger.Info("ConnCloseHandler player=%+v", *player)
	if player.ConnSeq != header.Seq || (player.ConningSeq > 0 && (player.ConningSeq != header.Seq)) {
		logger.Info("conn close, but seq not match, player valid connseq:%v closing seq:%d conning seq:%v for uid:%v",
			player.ConnSeq, header.Seq, player.ConningSeq, header.PlayerID)
		return
	}
	if player.OutDone != nil {
		logger.Info("conn close, outdone channel close for uid:%v", header.PlayerID)
		close(player.OutDone)
		player.OutDone = nil
	}

	pmgr.RemovePlayer(int(header.PlayerID))
	logger.Info("ConnCloseHandler-pmgr.RemovePlayer uid: %v", header.PlayerID)

	common.PlayerMap.Delete(header.PlayerID)

	logger.Info("player close outdone channel uid: %v", header.PlayerID)
	//更新用户的在线状态
	//db.UpdatePlayerOnlineState(header.PlayerID, 0)
}

func LoginHandler(conn net.Conn, header pb.MessageHeader, msg interface{}) {
	req := msg.(*pb.GameLogonReq)
	logger.Info("****login req header:%+v body:%+v", header, req)
	var err_num common.ErrorType = common.Error_OK

	var resp pb.GameLogonRsp
	var player *common.GamePlayer
	for {
		//首先验证token是否合法
		if !db.TokenAccess(header.PlayerID, req.Token) {
			err_num = common.Error_Check_Token_Failed
			logger.Notic("LoginHandler uid:%v failed:%v ", header.PlayerID, err_num)
			break
		}

		//uuid获取到以后
		player, err_num = pmgr.GetPlayer(uint32(header.PlayerID))
		if err_num != common.Error_OK || player == nil {
			err_num = common.Error_Player_Not_Found
			logger.Notic("get player uid:%v failed:%v seq:%v", header.PlayerID, err_num, header.Seq)
			break
		}
		player.ConningSeq = header.Seq

		//update conn into player
		player.UpdateConn(conn)

		resp.Gold, resp.Dimond, resp.Tili, resp.CurLevelId, resp.SyncId = db.GetUserInfo(header.PlayerID)
		ubase, err := db.GetUserBaseInfo(header.PlayerID)
		if err != nil {
			err_num = common.Error_Op_Db_Failed
			logger.Error("LoginHandler failed err=%v", err)
			break
		}
		resp.Gold = ubase.User_star
		resp.Dimond = ubase.User_dimond
		resp.Tili = ubase.User_tili
		resp.CurLevelId = ubase.Cur_level
		resp.SyncId = ubase.Sync_id
		resp.PlaneNum = ubase.Plan_num
		resp.BoomNum = ubase.Boom_num
		resp.RainbowNum = ubase.Rainbow_num

		resp.RecentQuestid = db.GetUserRecentQuestid(header.PlayerID)

		player.ConnSeq = header.Seq
		break
	}
	if player != nil {
		player.ConningSeq = 0
	}
	pmgr.Players_map.Set(header.PlayerID, player)

	if err_num == common.Error_OK {
		vv := common.PlayerMap.Get(uint32(header.PlayerID))
		if vv == nil {
			logger.Info("add player map uid:%d seq:%v", header.PlayerID, header.Seq)
			logger.Info("LoginHandler player=%+v", *player)
			common.PlayerMap.Set(uint32(header.PlayerID), 1)

			go ConnWriter(player)
		}
		//更新用户的在线状态
		//db.UpdatePlayerOnlineState(header.PlayerID, 1)
	}

	//resp.Error = int32(err_num)
	header.ErrorCode = uint32(err_num)
	resp.Curtime = int32(time.Now().Unix())

	logger.Info("LoginHandler resp=%+v", resp)
	SendMessage(player, conn, header, pb.MSGID_MsgID_SC_Game_Logon_Rsp, &resp)

}

func HeartBeatHandler(conn net.Conn, header pb.MessageHeader, msg interface{}) {
	req, ok := msg.(*pb.GameHeartBeatReq)
	if !ok {
		logger.Notic("error invalid message body, header:%+v", header)
		return
	}
	//logger.Info("HeartBeatHandler， req:%+v", req)
	var player *common.GamePlayer
	var err_num common.ErrorType = common.Error_OK
	for {
		player, err_num = pmgr.GetPlayer(header.PlayerID)
		if err_num != common.Error_OK || player == nil {
			err_num = common.Error_Player_Not_Found
			logger.Notic("get player uid:%v failed:%v seq:%v", header.PlayerID, err_num, header.Seq)
			break
		}
		break
	}
	var resp pb.GameHeartBeatRsp
	resp.Uid = req.Uid
	resp.Curtime = int32(time.Now().Unix())
	//logger.Info("HeartBeatHandler， resp:%+v", resp)
	if player != nil {
		//防止还未登录就发送心跳 此时不用回包
		SendMessage(player, conn, header, pb.MSGID_MsgID_SC_Game_HeartBeat_Rsp, &resp)
	}

}

func GetNewGuideReqHandler(conn net.Conn, header pb.MessageHeader, msg interface{}) {
	req, ok := msg.(*pb.GameGetNewGuideDataReq)
	if !ok {
		logger.Notic("GetNewGuideReqHandler error invalid message body, header:%+v", header)
		return
	}
	logger.Info("GetNewGuideReqHandler， req:%+v", req)

	var player *common.GamePlayer
	var err_num common.ErrorType = common.Error_OK
	var resp pb.GameGetNewGuideDataRsp
	for {
		player, err_num = pmgr.GetPlayer(header.PlayerID)
		if err_num != common.Error_OK || player == nil {
			err_num = common.Error_Player_Not_Found
			logger.Notic("get player uid:%v failed:%v ", header.PlayerID, err_num)
			break
		}

		datas, err := db.GetNewGuideData(header.PlayerID)
		if err != nil {
			err_num = common.Error_Op_Db_Failed
			logger.Notic("GetNewGuideReqHandler uid:%v failed:%v ", header.PlayerID, err)
			break
		}

		resp.Data = append(resp.Data, datas...)
		break
	}

	header.ErrorCode = uint32(err_num)
	logger.Info("GetNewGuideReqHandler resp=%+v", resp)
	SendMessage(player, conn, header, pb.MSGID_MsgID_SC_Game_GetNewGuideData_Rsp, &resp)
}

func GetSignDataReqHandler(conn net.Conn, header pb.MessageHeader, msg interface{}) {
	req, ok := msg.(*pb.GameGetSignDataReq)
	if !ok {
		logger.Notic("GetSignDataReqHandler error invalid message body, header:%+v", header)
		return
	}
	logger.Info("GetSignDataReqHandler， req:%+v", req)

	var player *common.GamePlayer
	var err_num common.ErrorType = common.Error_OK
	var resp pb.GameGetSignDataRsp
	for {
		player, err_num = pmgr.GetPlayer(header.PlayerID)
		if err_num != common.Error_OK || player == nil {
			err_num = common.Error_Player_Not_Found
			logger.Notic("get player uid:%v failed:%v ", header.PlayerID, err_num)
			break
		}

		signinfo := db.GetSignInfo(header.PlayerID)
		if signinfo == nil {
			logger.Notic("GetSignDataReqHandler signconfig failed ")
			err_num = common.Error_Check_Cfg_NotFound
			break
		}

		resp.SignDay = signinfo.Sign_day
		resp.IsSigned = signinfo.Is_signed
		resp.SignFin = signinfo.Sign_state
		break
	}

	header.ErrorCode = uint32(err_num)
	logger.Info("GetSignDataReqHandler resp=%+v", resp)
	SendMessage(player, conn, header, pb.MSGID_MsgID_SC_Game_GetSignData_Rsp, &resp)
}

func QuestGetAllHandler(conn net.Conn, header pb.MessageHeader, msg interface{}) {
	req, ok := msg.(*pb.GameQuestGetAllReq)
	if !ok {
		logger.Notic("QuestGetAllHandler error invalid message body, header:%+v", header)
		return
	}
	logger.Info("QuestGetAllHandler， req:%+v", req)

	var player *common.GamePlayer
	var err_num common.ErrorType = common.Error_OK
	var resp pb.GameQuestGetAllRsp
	for {
		player, err_num = pmgr.GetPlayer(header.PlayerID)
		if err_num != common.Error_OK || player == nil {
			err_num = common.Error_Player_Not_Found
			logger.Notic("get player uid:%v failed:%v ", header.PlayerID, err_num)
			break
		}

		//从数据库取出数据
		items, err := db.GetAllTaskInfo(header.PlayerID)
		if err != nil {
			err_num = common.Error_Op_Db_Failed
			logger.Error("QuestGetAllHandler failed err=%v", err)
			break
		}

		taskidlist, err := db.GetTaskListID(header.PlayerID)
		if err != nil {
			err_num = common.Error_Op_Db_Failed
			logger.Error("QuestGetAllHandler failed err=%v", err)
			break
		}

		resp.Tasklist = append(resp.Tasklist, taskidlist...)

		resp.Items = items
		resp.Time = uint32(time.Now().Unix())
		break
	}

	header.ErrorCode = uint32(err_num)
	logger.Info("QuestGetAllHandler resp=%+v", resp)
	SendMessage(player, conn, header, pb.MSGID_MsgID_SC_Game_QuestGetAll_Rsp, &resp)
}

func GameGmModiftyHandler(conn net.Conn, header pb.MessageHeader, msg interface{}) {
	req, ok := msg.(*pb.GameGmModiftyReq)
	if !ok || req == nil {
		logger.Notic("QuestGetAllHandler error invalid message body, header:%+v", header)
		return
	}
	logger.Info("GameGmModiftyHandler req=%+v", req)
	var player *common.GamePlayer
	var err_num common.ErrorType = common.Error_OK
	var resp pb.GameGmModiftyRsp

	for {
		player, err_num = pmgr.GetPlayer(header.PlayerID)
		if err_num != common.Error_OK || player == nil {
			err_num = common.Error_Player_Not_Found
			logger.Notic("GameGmModiftyHandler uid:%v failed:%v seq:%v", header.PlayerID, err_num, header.Seq)
			break
		}

		if req.Optype == common.Enum_GM_Optype_CLeanData {
			err := db.GMClearUserData(header.PlayerID)
			if err != nil {
				err_num = common.Error_Op_Db_Failed
				logger.Notic("GameGmModiftyHandler uid:%v failed:%v err:%v", header.PlayerID, err_num, err)
				break
			}
		} else if req.Optype == common.Enum_GM_Optype_OpearteStar {
			if len(req.Param) < 2 {
				err_num = common.Error_Op_Db_Failed
				logger.Notic("GameGmModiftyHandler param not leagl req=%+v", *req)
				break
			}

			err := db.GMOperateStar(header.PlayerID, req.Param[0], req.Param[1])
			if err != nil {
				err_num = common.Error_Op_Db_Failed
				logger.Notic("GameGmModiftyHandler failed err=%+v", err)
				break
			}

		} else if req.Optype == common.Enum_GM_Optype_OpearteTili {
			if len(req.Param) < 2 {
				err_num = common.Error_Op_Db_Failed
				logger.Notic("GameGmModiftyHandler param not leagl req=%+v", *req)
				break
			}

			err := db.GMOperateTili(header.PlayerID, req.Param[0], req.Param[1])
			if err != nil {
				err_num = common.Error_Op_Db_Failed
				logger.Notic("GameGmModiftyHandler failed err=%+v", err)
				break
			}
		} else if req.Optype == common.Enum_GM_Optype_OpearteUSD {
			if len(req.Param) < 2 {
				err_num = common.Error_Op_Db_Failed
				logger.Notic("GameGmModiftyHandler param not leagl req=%+v", *req)
				break
			}

			err := db.GMOperateUSD(header.PlayerID, req.Param[0], req.Param[1])
			if err != nil {
				err_num = common.Error_Op_Db_Failed
				logger.Notic("GameGmModiftyHandler failed err=%+v", err)
				break
			}
		} else if req.Optype == common.Enum_GM_Optype_OpearteItem {
			if len(req.Param) < 3 {
				err_num = common.Error_Op_Db_Failed
				logger.Notic("GameGmModiftyHandler param not leagl req=%+v", req)
				break
			}

			err := db.GMOperateItem(header.PlayerID, req.Param[0], req.Param[1], req.Param[2])
			if err != nil {
				err_num = common.Error_Op_Db_Failed
				logger.Notic("GameGmModiftyHandler failed err=%+v", err)
				break
			}
		} else if req.Optype == common.Enum_GM_Optype_OpearteLevel {
			if len(req.Param) < 1 {
				err_num = common.Error_Op_Db_Failed
				logger.Notic("GameGmModiftyHandler param not leagl req=%+v", *req)
				break
			}

			err := db.GMOperateCurLevel(header.PlayerID, req.Param[0])
			if err != nil {
				err_num = common.Error_Op_Db_Failed
				logger.Notic("GameGmModiftyHandler failed err=%+v", err)
				break
			}
		}

		break
	}

	header.ErrorCode = uint32(err_num)
	logger.Info("GameGmModiftyHandler resp=%+v", resp)
	SendMessage(player, conn, header, pb.MSGID_MsgID_SC_Game_GmModifty_Rsp, &resp)
}

func QuestFinishOfflineHandler(conn net.Conn, header pb.MessageHeader, msg interface{}) {
	req, ok := msg.(*pb.GameQuestFinishOfflineReq)
	if !ok || req == nil {
		logger.Notic("QuestGetAllHandler error invalid message body, header:%+v", header)
		return
	}
	logger.Info("QuestFinishOfflineHandler req=%+v", req)
	var player *common.GamePlayer
	var err_num common.ErrorType = common.Error_OK
	var resp pb.GameOfflineCommRsp
	var newSyncId int64 = 0
	var err error
	for {
		player, err_num = pmgr.GetPlayer(header.PlayerID)
		if err_num != common.Error_OK || player == nil {
			err_num = common.Error_Player_Not_Found
			logger.Notic("QuestFinishOfflineHandler uid:%v failed:%v ", header.PlayerID, err_num)
			break
		}

		err, err_num = db.CheckSyncID(req.GetBaseInfo().Syncid, header.PlayerID)
		if err_num != common.Error_OK {
			//err_num = common.Error_Check_Syncid_Failed
			logger.Notic("QuestFinishOfflineHandler uid:%v failed:%v err:%v", header.PlayerID, err_num, err)
			break
		}

		//检查前置关卡和消耗星星
		quesetinfo := jconf.GetTaskDataInfo(req.QuestId)
		if quesetinfo == nil {
			err_num = common.Error_Check_Cfg_NotFound
			logger.Notic("QuestFinishOfflineHandler uid:%v failed:%v seq:%v", header.PlayerID, err_num, header.Seq)
			break
		}
		if quesetinfo.PreTaskID != 0 {
			err = db.CheckQuestFinished(header.PlayerID, quesetinfo.PreTaskID)
			if err != nil {
				err_num = common.Error_Check_PreQuest_notFin
				logger.Notic("QuestFinishOfflineHandler uid:%v failed:%v seq:%v", header.PlayerID, err_num, header.Seq)
				break
			}
		}

		ustar, _, _, _, _ := db.GetUserInfo(header.PlayerID)
		if ustar < quesetinfo.CostStarNum {
			err_num = common.Error_Check_StarNum_notEnough
			logger.Notic("QuestFinishOfflineHandler uid:%v failed:%v seq:%v", header.PlayerID, err_num, header.Seq)
			break
		}

		//进行更新数据
		err = db.UpdateFinsTask(req, header.PlayerID, quesetinfo.CostStarNum)
		if err != nil {
			err_num = common.Error_Op_Db_Failed
			logger.Notic("QuestFinishOfflineHandler uid:%v failed:%v seq:%v", header.PlayerID, err_num, header.Seq)
			break
		}

		//保存玩家任务列表以及最近完成的任务
		err = db.UpdateFinTaskExtra(req, header.PlayerID)
		if err != nil {
			err_num = common.Error_Op_Db_Failed
			logger.Notic("QuestFinishOfflineHandler uid:%v failed:%v seq:%v", header.PlayerID, err_num, header.Seq)
			break
		}

		//都成功的话 则更新同步包id
		err, newSyncId = db.AddSyncIdIndex(header.PlayerID, 1)
		if err != nil {
			err_num = common.Error_Op_Db_Failed
			logger.Error("QuestFinishOfflineHandler failed err=%v", err)
			break
		}

		break
	}

	header.ErrorCode = uint32(err_num)
	resp.Syncid = newSyncId
	if err_num != common.Error_OK {
		resp.Syncid = req.BaseInfo.Syncid
	}
	resp.Cmd = int32(pb.MSGID_MsgID_CS_Game_QuestFinishOffline_Req)
	logger.Info("QuestFinishOfflineHandler resp=%+v", resp)
	SendMessage(player, conn, header, pb.MSGID_MsgID_SC_Game_OfflineComm_Rsp, &resp)

}

func LevelStartHandler(conn net.Conn, header pb.MessageHeader, msg interface{}) {
	req, ok := msg.(*pb.GameLevelStartReq)
	if !ok {
		logger.Notic("LevelStartHandler error invalid message body, header:%+v", header)
		return
	}
	logger.Info("LevelStartHandler， req:%+v", req)

	var player *common.GamePlayer
	var err_num common.ErrorType = common.Error_OK
	var resp pb.GameOfflineCommRsp
	var newSyncId int64 = 0
	var err error
	for {
		player, err_num = pmgr.GetPlayer(header.PlayerID)
		if err_num != common.Error_OK || player == nil {
			err_num = common.Error_Player_Not_Found
			logger.Notic("LevelStartHandler uid:%v failed:%v seq:%v", header.PlayerID, err_num, header.Seq)
			break
		}

		err, err_num = db.CheckSyncID(req.GetBaseInfo().Syncid, header.PlayerID)
		if err_num != common.Error_OK {
			//err_num = common.Error_Check_Syncid_Failed
			logger.Notic("LevelStartHandler uid:%v failed:%v err:%v", header.PlayerID, err_num, err)
			break
		}

		//需要检查前置关卡
		linfo := jconf.GetMapSeqInfoByMapID(req.LevelId)
		if linfo == nil {
			err_num = common.Error_Check_Cfg_NotFound
			logger.Notic("LevelStartHandler uid:%v failed:%v seq:%v", header.PlayerID, err_num, header.Seq)
			break
		}

		//检查前置关卡是否完成  id为一则不需要检查
		if linfo.ID > 1 {
			preinfo := jconf.GetMapSeqInfo(linfo.ID - 1)
			if preinfo == nil {
				err_num = common.Error_Check_Cfg_NotFound
				logger.Notic("LevelStartHandler uid:%v failed:%v seq:%v,info=%+v", header.PlayerID, err_num, header.Seq, linfo)
				break
			}

			//检查当前前置关卡完成状态
			err := db.CheckLevelFin(header.PlayerID, preinfo.LevelID)
			if err != nil {
				err_num = common.Error_Check_Pre_levelNotFin
				logger.Notic("LevelStartHandler uid:%v failed:%v seq:%v", header.PlayerID, err_num, header.Seq)
				break
			}
		}

		//检查物品数量是否足够
		ubase, err := db.GetUserBaseInfo(header.PlayerID)
		if err != nil || ubase == nil {
			err_num = common.Error_Player_Not_Found
			logger.Notic("LevelStartHandler uid:%v failed:%v err:%v", header.PlayerID, err_num, err)
			break
		}

		if ubase.User_tili < 1 {
			err_num = common.Error_Check_Tili_NotEnough
			logger.Notic("LevelStartHandler uid:%v failed:%v err:%v", header.PlayerID, err_num, err)
			break
		}

		if ubase.Plan_num < req.UsePlane || ubase.Boom_num < req.UseBoom || ubase.Rainbow_num < req.UseRainbow {
			err_num = common.Error_Check_Item_NotEnough
			logger.Notic("LevelStartHandler uid:%v failed:%v err:%v", header.PlayerID, err_num, err)
			break
		}

		//条件满足 扣除道具
		ubase.User_tili -= 1
		ubase.Plan_num -= req.UsePlane
		ubase.Boom_num -= req.UseBoom
		ubase.Rainbow_num -= req.UseRainbow
		err = db.UpdateUserBaseInfo(header.PlayerID, ubase)
		if err != nil {
			err_num = common.Error_Op_Db_Failed
			logger.Error("LevelStartHandler failed err=%v", err)
			break
		}

		//插入关卡数据
		err = db.UpdateLevelInfo(header.PlayerID, req, 0)
		if err != nil {
			err_num = common.Error_Op_Db_Failed
			logger.Error("LevelStartHandler failed err=%v", err)
			break
		}

		//最后更新syncid
		err, newSyncId = db.AddSyncIdIndex(header.PlayerID, 1)
		if err != nil {
			err_num = common.Error_Op_Db_Failed
			logger.Error("LevelStartHandler failed err=%v", err)
			break
		}

		break
	}

	header.ErrorCode = uint32(err_num)
	resp.Syncid = newSyncId
	if err_num != common.Error_OK {
		resp.Syncid = req.BaseInfo.Syncid
	}
	resp.Cmd = int32(pb.MSGID_MsgID_CS_Game_LevelStart_Req)
	logger.Info("LevelStartHandler resp=%+v", resp)
	SendMessage(player, conn, header, pb.MSGID_MsgID_SC_Game_OfflineComm_Rsp, &resp)
}

func LevelEndHandler(conn net.Conn, header pb.MessageHeader, msg interface{}) {
	req, ok := msg.(*pb.GameLevelEndReq)
	if !ok {
		logger.Notic("LevelEndHandler error invalid message body, header:%+v", header)
		return
	}
	logger.Info("LevelEndHandler， req:%+v", req)

	var player *common.GamePlayer
	var err_num common.ErrorType = common.Error_OK
	var resp pb.GameOfflineCommRsp
	var newSyncId int64 = 0
	var err error
	for {
		player, err_num = pmgr.GetPlayer(header.PlayerID)
		if err_num != common.Error_OK || player == nil {
			err_num = common.Error_Player_Not_Found
			logger.Notic("LevelEndHandler uid:%v failed:%v", header.PlayerID, err_num)
			break
		}

		err, err_num = db.CheckSyncID(req.GetBaseInfo().Syncid, header.PlayerID)
		if err_num != common.Error_OK {
			logger.Notic("LevelStartHandler uid:%v  err:%v", header.PlayerID, err)
			break
		}

		//检查一下是否有当前关卡的开始记录
		err = db.CheckLevelStart(req.LevelId, req.BattleId, header.PlayerID, req.Result)
		if err != nil {
			err_num = common.Error_Check_Level_NotStart
			logger.Notic("LevelEndHandler uid:%v failed:%v err:%v", header.PlayerID, err_num, err)
			break
		}

		ubase, err := db.GetUserBaseInfo(header.PlayerID)
		if err != nil || ubase == nil {
			err_num = common.Error_Player_Not_Found
			logger.Notic("LevelEndHandler uid:%v  err:%v", header.PlayerID, err)
			break
		}

		ubase.Cur_level = req.LevelId
		//根据结果操作
		if req.Result == 0 {
			//成功
			ubase.User_star += req.RewardStar
			ubase.User_dimond += req.RewardUsd
			ubase.User_tili += 1

			//取得下一关
			linfo := jconf.GetMapSeqInfoByMapID(req.LevelId)
			if linfo != nil {
				nexinfo := jconf.GetMapSeqInfo(linfo.ID + 1)
				if nexinfo != nil {
					ubase.Cur_level = nexinfo.LevelID
				}
			}

		} else {
			//失败

		}

		//
		err = db.UpdateUserBaseInfo(header.PlayerID, ubase)
		if err != nil {
			err_num = common.Error_Op_Db_Failed
			logger.Error("LevelEndHandler failed err=%v", err)
			break
		}

		//最后更新syncid
		err, newSyncId = db.AddSyncIdIndex(header.PlayerID, 1)
		if err != nil {
			err_num = common.Error_Op_Db_Failed
			logger.Error("LevelEndHandler failed err=%v", err)
			break
		}

		break
	}

	header.ErrorCode = uint32(err_num)
	resp.Syncid = newSyncId
	if err_num != common.Error_OK {
		resp.Syncid = req.BaseInfo.Syncid
	}
	resp.Cmd = int32(pb.MSGID_MsgID_CS_Game_LevelEnd_Req)
	logger.Info("LevelStartHandler resp=%+v", resp)
	SendMessage(player, conn, header, pb.MSGID_MsgID_SC_Game_OfflineComm_Rsp, &resp)
}

func ContinueReqHandler(conn net.Conn, header pb.MessageHeader, msg interface{}) {
	req, ok := msg.(*pb.GameContinueReq)
	if !ok {
		logger.Notic("ContinueReqHandler error invalid message body, header:%+v", header)
		return
	}
	logger.Info("ContinueReqHandler， req:%+v", req)

	var player *common.GamePlayer
	var err_num common.ErrorType = common.Error_OK
	var resp pb.GameOfflineCommRsp
	var newSyncId int64 = 0
	var err error
	for {
		player, err_num = pmgr.GetPlayer(header.PlayerID)
		if err_num != common.Error_OK || player == nil {
			err_num = common.Error_Player_Not_Found
			logger.Notic("ContinueReqHandler player not found:%v seq:%v", header.PlayerID, err_num, header.Seq)
			break
		}
		err, err_num = db.CheckSyncID(req.BaseInfo.Syncid, header.PlayerID)
		if err_num != common.Error_OK {
			//err_num = common.Error_Check_Syncid_Failed
			logger.Notic("ContinueReqHandler uid:%v  err:%v", header.PlayerID, err)
			break
		}

		//获取配置
		cfg := jconf.GetContinueStep(req.Cnt)
		if cfg == nil {
			err_num = common.Error_Check_Cfg_NotFound
			logger.Notic("ContinueReqHandler get config failed")
			break
		}

		//扣除美金
		ubase, err := db.GetUserBaseInfo(header.PlayerID)
		if err != nil || ubase == nil {
			err_num = common.Error_Player_Not_Found
			logger.Notic("ContinueReqHandler uid:%v failed:%v err:%v", header.PlayerID, err_num, err)
			break
		}
		if ubase.User_dimond < cfg.UsdCost {
			err_num = common.Error_Check_USD_NotEnough
			logger.Notic("ContinueReqHandler uid:%v failed:%v err:%v", header.PlayerID, err_num, err)
			break
		}

		ubase.User_dimond -= cfg.UsdCost

		err = db.UpdateUserBaseInfo(header.PlayerID, ubase)
		if err != nil {
			err_num = common.Error_Op_Db_Failed
			logger.Notic("ContinueReqHandler uid:%v failed:%v err:%v", header.PlayerID, err_num, err)
			break
		}

		//最后更新syncid
		err, newSyncId = db.AddSyncIdIndex(header.PlayerID, 1)
		if err != nil {
			err_num = common.Error_Op_Db_Failed
			logger.Error("ContinueReqHandler failed err=%v", err)
			break
		}

		break
	}
	header.ErrorCode = uint32(err_num)
	resp.Syncid = newSyncId
	if err_num != common.Error_OK {
		resp.Syncid = req.BaseInfo.Syncid
	}
	resp.Cmd = int32(pb.MSGID_MsgID_CS_Game_Continue_Req)
	logger.Info("ContinueReqHandler resp=%+v", resp)
	SendMessage(player, conn, header, pb.MSGID_MsgID_SC_Game_OfflineComm_Rsp, &resp)
}

func NewGuideFinReqHandler(conn net.Conn, header pb.MessageHeader, msg interface{}) {
	req, ok := msg.(*pb.GameNewGuideFinReq)
	if !ok {
		logger.Notic("NewGuideFinReqHandler error invalid message body, header:%+v", header)
		return
	}
	logger.Info("NewGuideFinReqHandler， req:%+v", req)

	var player *common.GamePlayer
	var err_num common.ErrorType = common.Error_OK
	var resp pb.GameOfflineCommRsp
	var newSyncId int64 = 0
	var err error
	for {
		player, err_num = pmgr.GetPlayer(header.PlayerID)
		if err_num != common.Error_OK || player == nil {
			err_num = common.Error_Player_Not_Found
			logger.Notic("NewGuideFinReqHandler uid:%v failed:%v seq:%v", header.PlayerID, err_num, header.Seq)
			break
		}

		err, err_num = db.CheckSyncID(req.BaseInfo.Syncid, header.PlayerID)
		if err_num != common.Error_OK {
			//err_num = common.Error_Check_Syncid_Failed
			logger.Notic("NewGuideFinReqHandler uid:%v failed:%v err:%v", header.PlayerID, err_num, err)
			break
		}

		//插入记录
		err = db.UpdateNewGuideInfo(req.Info, header.PlayerID)
		if err != nil {
			err_num = common.Error_Op_Db_Failed
			logger.Error("NewGuideFinReqHandler failed err=%v", err)
			break
		}

		//最后更新syncid
		err, newSyncId = db.AddSyncIdIndex(header.PlayerID, 1)
		if err != nil {
			err_num = common.Error_Op_Db_Failed
			logger.Error("NewGuideFinReqHandler failed err=%v", err)
			break
		}

		break
	}

	header.ErrorCode = uint32(err_num)
	resp.Syncid = newSyncId
	if err_num != common.Error_OK {
		resp.Syncid = req.BaseInfo.Syncid
	}
	resp.Cmd = int32(pb.MSGID_MsgID_CS_Game_NewGuideFin_Req)
	logger.Info("NewGuideFinReqHandler resp=%+v", resp)
	SendMessage(player, conn, header, pb.MSGID_MsgID_SC_Game_OfflineComm_Rsp, &resp)
}

func TaskGroupRewardHandler(conn net.Conn, header pb.MessageHeader, msg interface{}) {
	req, ok := msg.(*pb.GameTaskGroupRewardReq)
	if !ok {
		logger.Notic("TaskGroupRewardHandler error invalid message body, header:%+v", header)
		return
	}
	logger.Info("TaskGroupRewardHandler， req:%+v", req)

	var player *common.GamePlayer
	var err_num common.ErrorType = common.Error_OK
	var resp pb.GameOfflineCommRsp
	var newSyncId int64 = 0
	var err error
	for {
		player, err_num = pmgr.GetPlayer(header.PlayerID)
		if err_num != common.Error_OK || player == nil {
			err_num = common.Error_Player_Not_Found
			logger.Notic("TaskGroupRewardHandler uid:%v failed:%v seq:%v", header.PlayerID, err_num, header.Seq)
			break
		}

		err, err_num = db.CheckSyncID(req.BaseInfo.Syncid, header.PlayerID)
		if err_num != common.Error_OK {
			//err_num = common.Error_Check_Syncid_Failed
			logger.Notic("TaskGroupRewardHandler uid:%v failed:%v err:%v", header.PlayerID, err_num, err)
			break
		}

		//获取配置
		//trcfg := jconf.GetTaskGroupReward(req.TaskId)
		trcfg := jconf.GetTaskGruopInfo(req.TaskId)
		if trcfg == nil {
			logger.Notic("TaskGroupRewardHandler signconfig failed trcfg=%v")
			err_num = common.Error_Check_Cfg_NotFound
			break
		}

		//需要检查以下任务组是否已经完成
		isallfin := true
		for i := 0; i < len(trcfg.GruopIDs); i++ {
			err := db.CheckQuestFinished(header.PlayerID, trcfg.GruopIDs[i])
			if err != nil {

				isallfin = false
				break
			}
		}

		if !isallfin {
			logger.Notic("TaskGroupRewardHandler CheckQuestFinished failed trcfg=%v")
			err_num = common.Error_Check_TaskGroup_NotFin
			break
		}

		tsrcfg := jconf.GetTaskGroupReward(trcfg.RGroupID)

		if tsrcfg == nil || len(tsrcfg.Rewards) != len(tsrcfg.RewardNum) {
			logger.Notic("TaskGroupRewardHandler signconfig failed trcfg=%v")
			err_num = common.Error_Check_Cfg_NotFound
			break
		}

		//检查是否已经领取过了
		if db.IsTaskGroupFetched(header.PlayerID, req.TaskId) {
			logger.Notic("TaskGroupRewardHandler task already fetched")
			err_num = common.Error_Check_TaskGroup_Already_Fetched
			break
		}

		//增加奖励
		err = db.RewardTaskGruop(header.PlayerID, tsrcfg.Rewards, tsrcfg.RewardNum)
		if err != nil {
			logger.Notic("TaskGroupRewardHandler RewardTaskGruop failed trcfg=%v", *trcfg)
			err_num = common.Error_Check_TaskGroup_Reward_Failed
			break
		}

		//讲奖励记录插入
		err = db.UpdateTaskGroupFetched(header.PlayerID, req.TaskId)
		if err != nil {
			logger.Notic("TaskGroupRewardHandler UpdateTaskGroupFetched failed err=%v", err)
			err_num = common.Error_Op_Db_Failed
			break
		}

		//最后更新syncid
		err, newSyncId = db.AddSyncIdIndex(header.PlayerID, 1)
		if err != nil {
			err_num = common.Error_Op_Db_Failed
			logger.Error("TaskGroupRewardHandler failed err=%v", err)
			break
		}

		break
	}

	header.ErrorCode = uint32(err_num)
	resp.Syncid = newSyncId
	if err_num != common.Error_OK {
		resp.Syncid = req.BaseInfo.Syncid
	}
	resp.Cmd = int32(pb.MSGID_MsgID_CS_Game_TaskGroupReward_Req)
	logger.Info("TaskGroupRewardHandler resp=%+v", resp)
	SendMessage(player, conn, header, pb.MSGID_MsgID_SC_Game_OfflineComm_Rsp, &resp)
}

func DoSignHandler(conn net.Conn, header pb.MessageHeader, msg interface{}) {
	req, ok := msg.(*pb.GameDoSignReq)
	if !ok {
		logger.Notic("DoSignHandler error invalid message body, header:%+v", header)
		return
	}
	logger.Info("DoSignHandler， req:%+v", req)

	var player *common.GamePlayer
	var err_num common.ErrorType = common.Error_OK
	var resp pb.GameOfflineCommRsp
	var newSyncId int64 = 0
	var err error
	for {
		player, err_num = pmgr.GetPlayer(header.PlayerID)
		if err_num != common.Error_OK || player == nil {
			err_num = common.Error_Player_Not_Found
			logger.Notic("DoSignHandler uid:%v failed:%v seq:%v", header.PlayerID, err_num, header.Seq)
			break
		}

		err, err_num = db.CheckSyncID(req.BaseInfo.Syncid, header.PlayerID)
		if err_num != common.Error_OK {
			//err_num = common.Error_Check_Syncid_Failed
			logger.Notic("QuestChangeItemHandler uid:%v failed:%v err:%v", header.PlayerID, err_num, err)
			break
		}

		sinfo := db.GetSignInfo(header.PlayerID)
		if sinfo == nil {
			logger.Notic("DoSignHandler signconfig failed ")
			err_num = common.Error_Check_Cfg_NotFound
			break
		}

		if sinfo.Sign_state != 0 {
			logger.Notic("DoSignHandler already signed sinfo=%+v", *sinfo)
			err_num = common.Error_Check_Is_Signed
			break
		}

		//如果签到状态位已签到 这判断时间是否已经进入下一天
		if sinfo.Is_signed != 0 {
			nowt := time.Now()

			tm := time.Unix(int64(sinfo.Last_signtime), 0)
			if nowt.Day() == tm.Day() && nowt.Month() == tm.Month() && nowt.Year() == tm.Year() {
				//当天已经签到
				logger.Notic("DoSignHandler already signed sinfo=%+v", *sinfo)
				err_num = common.Error_Check_Is_Signed
				break
			}

			sinfo.Is_signed = 0
		}

		//获取下一个签到天数的奖励
		signcfg := jconf.GetSignDataInfoByDay(sinfo.Sign_day + 1)
		if signcfg == nil {
			logger.Notic("DoSignHandler GetSignDataInfoByDay failed ")
			err_num = common.Error_Check_Cfg_NotFound
			break
		}

		//完成签到给奖励

		err = db.RewardSign(header.PlayerID, signcfg)
		if err != nil {
			logger.Notic("DoSignHandler RewardSign failed err=%v", err)
			err_num = common.Error_Check_Sign_Reward_Failed
			break
		}

		//更新签到进度
		sinfo.Sign_day++
		sinfo.Sign_state = 1
		sinfo.Last_signtime = int32(time.Now().Unix())
		if sinfo.Sign_day >= 7 {
			//七天签到已完成
			sinfo.Sign_state = 1
		}

		err = db.UpdateSignInfo(sinfo)
		if err != nil {
			logger.Notic("DoSignHandler UpdateSignInfo failed err=%v", err)
			err_num = common.Error_Op_Db_Failed
			break
		}

		//最后更新syncid
		err, newSyncId = db.AddSyncIdIndex(header.PlayerID, 1)
		if err != nil {
			err_num = common.Error_Op_Db_Failed
			logger.Error("LevelEndHandler failed err=%v", err)
			break
		}

		break
	}

	header.ErrorCode = uint32(err_num)
	resp.Syncid = newSyncId
	if err_num != common.Error_OK {
		resp.Syncid = req.BaseInfo.Syncid
	}
	resp.Cmd = int32(pb.MSGID_MsgID_CS_Game_DoSign_Req)
	logger.Info("DoSignHandler resp=%+v", resp)
	SendMessage(player, conn, header, pb.MSGID_MsgID_SC_Game_OfflineComm_Rsp, &resp)
}

func QuestChangeItemHandler(conn net.Conn, header pb.MessageHeader, msg interface{}) {
	req, ok := msg.(*pb.GameQuestChangeItemReq)
	if !ok {
		logger.Notic("QuestGetAllHandler error invalid message body, header:%+v", header)
		return
	}
	logger.Info("QuestGetAllHandler， req:%+v", req)

	var player *common.GamePlayer
	var err_num common.ErrorType = common.Error_OK
	var resp pb.GameOfflineCommRsp
	var newSyncId int64 = 0
	var err error
	for {
		player, err_num = pmgr.GetPlayer(header.PlayerID)
		if err_num != common.Error_OK || player == nil {
			err_num = common.Error_Player_Not_Found
			logger.Notic("QuestChangeItemHandler uid:%v failed:%v seq:%v", header.PlayerID, err_num, header.Seq)
			break
		}

		err, err_num = db.CheckSyncID(req.Syncid, header.PlayerID)
		if err_num != common.Error_OK {
			//err_num = common.Error_Check_Syncid_Failed
			logger.Notic("QuestChangeItemHandler uid:%v failed:%v err:%v", header.PlayerID, err_num, err)
			break
		}

		//更新
		err = db.UpdateQuestItem(req.QuestId, req.SelectItem, header.PlayerID)
		if err != nil {
			err_num = common.Error_Op_Db_Failed
			logger.Error("QuestChangeItemHandler failed err=%v", err)
			break
		}

		//都成功的话 则更新同步包id
		err, newSyncId = db.AddSyncIdIndex(header.PlayerID, 1)
		if err != nil {
			err_num = common.Error_Op_Db_Failed
			logger.Error("QuestChangeItemHandler failed err=%v", err)
			break
		}

		break
	}

	header.ErrorCode = uint32(err_num)
	resp.Syncid = newSyncId
	if err_num != common.Error_OK {
		resp.Syncid = req.Syncid
	}
	resp.Cmd = int32(pb.MSGID_MsgID_CS_Game_QuestChangeItem_Req)
	logger.Info("QuestChangeItemHandler resp=%+v", resp)
	SendMessage(player, conn, header, pb.MSGID_MsgID_SC_Game_OfflineComm_Rsp, &resp)
}
